﻿#include "LPProcessEllipse.h"

#include <QPainter>

struct LPProcessEllipsePrivate
{
    LPProcessEllipsePrivate():m_minValue(0),m_maxValue(100),m_precision(0),m_clockWise(true)
    ,m_showPercent(true),m_startAngle(90),m_ringPadding(10)
    ,m_ringWidth(25),m_backgroundColor(255, 255, 255)
    ,m_textColor(255, 255, 0),m_ringColor(255, 0, 0)
    ,m_ringBackgroundColor(255, 255, 255)
    ,m_circleColor(255, 0, 255),m_currentValue(0)
    {
    }
    double m_currentValue;            //当前值
    double m_minValue;                //最小值
    double m_maxValue;                //最大值

    bool m_clockWise;                 //顺时针逆时针
    bool m_showPercent;               //显示百分比

    int m_startAngle;                 //起始角度
    int m_ringPadding;                //圆环间距
    int m_ringWidth;                  //圆环宽度
    int m_precision;                  //精确度,小数点后几位

    QColor m_backgroundColor;         //背景颜色
    QColor m_textColor;               //文字颜色
    QColor m_ringColor;               //圆环外圈的颜色
    QColor m_ringBackgroundColor;     //初始颜色
    QColor m_circleColor;             //中心圆颜色

    QTimer* m_startTimer;              //定时器
};

LPProcessEllipse::LPProcessEllipse(QWidget *parent)
    :QWidget(parent),_P(new LPProcessEllipsePrivate)
{
    _P->m_startTimer = new QTimer(this);
    connect(_P->m_startTimer,&QTimer::timeout,[=]()
    {
        if(_P->m_currentValue==100)_P->m_currentValue=0;
        setValue(_P->m_currentValue);
        _P->m_currentValue++;
    });
}

LPProcessEllipse::~LPProcessEllipse()
{

}

void LPProcessEllipse::resizeEvent(QResizeEvent*)
{
    update();
}

void LPProcessEllipse::paintEvent(QPaintEvent *)
{
    int width = this->width();
    int height = this->height();
    int side = qMin(width, height);
    QPainter painter(this);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    painter.translate(width / 2, height / 2);
    painter.scale(side / 200.0, side / 200.0);

    drawBackground(&painter);
    //绘制进度
    drawRing(&painter);

    //绘制间隔,重新绘制一个圆遮住,产生间距效果
    if (_P->m_ringPadding > 0) {
        drawPadding(&painter);
    }

    //绘制中间圆
    drawCircle(&painter);
    //绘制当前值
    drawValue(&painter);
}

void LPProcessEllipse::drawBackground(QPainter *painter)
{
    int radius = 99;
    painter->save();
    painter->setPen(Qt::NoPen);
    //如果没有间距则设置成圆环的背景色
    painter->setBrush(_P->m_ringPadding == 0 ? _P->m_ringBackgroundColor : _P->m_backgroundColor);
    painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
    painter->restore();
}

void LPProcessEllipse::drawRing(QPainter *painter)
{
    int radius = 99 - _P->m_ringPadding;
    painter->save();
    painter->setPen(Qt::NoPen);
    painter->setBrush(_P->m_ringColor);

    QRectF rect(-radius, -radius, radius * 2, radius * 2);

    //计算总范围角度,当前值范围角度,剩余值范围角度
    double angleAll = 360.0;
    double angleCurrent = angleAll * ((_P->m_currentValue - _P->m_minValue) / (_P->m_maxValue - _P->m_minValue));
    double angleOther = angleAll - angleCurrent;

    //如果逆时针
    if (!_P->m_clockWise) {
        angleCurrent = -angleCurrent;
        angleOther = -angleOther;
    }

    //动态设置当前进度颜色
    QColor color = _P->m_ringColor;

    //绘制当前值饼圆
    painter->setBrush(color);
    painter->drawPie(rect, (_P->m_startAngle - angleCurrent) * 16, angleCurrent * 16);

    //绘制剩余值饼圆
    painter->setBrush(_P->m_ringBackgroundColor);
    painter->drawPie(rect, (_P->m_startAngle - angleCurrent - angleOther) * 16, angleOther * 16);

    painter->restore();
}

void LPProcessEllipse::drawPadding(QPainter *painter)
{
    int radius = 99 - _P->m_ringWidth - _P->m_ringPadding;
    painter->save();
    painter->setPen(Qt::NoPen);
    painter->setBrush(_P->m_backgroundColor);
    painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
    painter->restore();
}

void LPProcessEllipse::drawCircle(QPainter *painter)
{
    //文字的区域要减去进度的宽度及间距
    int radius = 99 - _P->m_ringWidth - (_P->m_ringPadding * 2);
    painter->save();
    painter->setPen(Qt::NoPen);
    painter->setBrush(_P->m_circleColor);
    painter->drawEllipse(-radius, -radius, radius * 2, radius * 2);
    painter->restore();
}

void LPProcessEllipse::drawValue(QPainter *painter)
{
    //文字的区域要减去进度的宽度及间距
    int radius = 99 - _P->m_ringWidth - (_P->m_ringPadding * 2);
    painter->save();
    painter->setPen(_P->m_textColor);

    QFont font;
    int fontSize = radius - (_P->m_showPercent ? 20 : 6);
    font.setPixelSize(fontSize);
    painter->setFont(font);

    QRectF textRect(-radius, -radius, radius * 2, radius * 2);
    QString strValue;
    if (_P->m_showPercent) {
        double percent = (_P->m_currentValue * 100) / (_P->m_maxValue - _P->m_minValue);
        strValue = QString("%1%").arg(percent, 0, 'f', _P->m_precision);
    } else {
        strValue = QString("%1").arg(_P->m_currentValue, 0, 'f', _P->m_precision);
    }

    painter->drawText(textRect, Qt::AlignCenter, strValue);
    painter->restore();
}

LPProcessEllipse& LPProcessEllipse::setValue(double value)
{
    _P->m_currentValue = value;
    if(_P->m_currentValue>_P->m_maxValue)return* this;
    update();
    return *this;
}

double LPProcessEllipse::getValue() const
{
    return _P->m_currentValue;
}

double LPProcessEllipse::getMaxValue() const
{
    return _P->m_maxValue;
}

LPProcessEllipse& LPProcessEllipse::setMaxValue(double maxValue)
{
    _P->m_maxValue = maxValue;
    update();
    return *this;
}

double LPProcessEllipse::getMinValue() const
{
    return _P->m_minValue;
}

LPProcessEllipse& LPProcessEllipse::setMinValue(double minValue)
{
    _P->m_minValue = minValue;
    update();
    return *this;
}

bool LPProcessEllipse::getClockWise() const
{
    return _P->m_clockWise;
}

LPProcessEllipse& LPProcessEllipse::setClockWise(bool clockWise)
{
    _P->m_clockWise = clockWise;
    update();
    return *this;
}

QColor LPProcessEllipse::getCircleColor() const
{
    return _P->m_circleColor;
}

LPProcessEllipse& LPProcessEllipse::setCircleColor(const QColor &circleColor)
{
    _P->m_circleColor = circleColor;
    update();
    return *this;
}

QColor LPProcessEllipse::getRingBackgroundColor() const
{
    return _P->m_ringBackgroundColor;
}

LPProcessEllipse& LPProcessEllipse::setRingBackgroundColor(const QColor &ringBackgroundColor)
{
    _P->m_ringBackgroundColor = ringBackgroundColor;
    update();
    return *this;
}

QColor LPProcessEllipse::getRingColor() const
{
    return _P->m_ringColor;
}

LPProcessEllipse& LPProcessEllipse::setRingColor(const QColor &ringColor)
{
    _P->m_ringColor = ringColor;
    update();
    return *this;
}

QColor LPProcessEllipse::getTextColor() const
{
    return _P->m_textColor;
}

LPProcessEllipse& LPProcessEllipse::setTextColor(const QColor &textColor)
{
    _P->m_textColor = textColor;
    update();
    return *this;
}

QColor LPProcessEllipse::getBackgroundColor() const
{
    return _P->m_backgroundColor;
}

LPProcessEllipse& LPProcessEllipse::setBackgroundColor(const QColor &backgroundColor)
{
    _P->m_backgroundColor = backgroundColor;
    update();
    return *this;
}

int LPProcessEllipse::getPrecision() const
{
    return _P->m_precision;
}

LPProcessEllipse& LPProcessEllipse::setPrecision(int precision)
{
    _P->m_precision = precision;
    update();
    return *this;
}

int LPProcessEllipse::getRingWidth() const
{
    return _P->m_ringWidth;
}

LPProcessEllipse& LPProcessEllipse::setRingWidth(int ringWidth)
{
    _P->m_ringWidth = ringWidth;
    update();
    return *this;
}

int LPProcessEllipse::getRingPadding() const
{
    return _P->m_ringPadding;
}

LPProcessEllipse& LPProcessEllipse::setRingPadding(int ringPadding)
{
    _P->m_ringPadding = ringPadding;
    update();
    return *this;
}

bool LPProcessEllipse::getShowPercent() const
{
    return _P->m_showPercent;
}

LPProcessEllipse& LPProcessEllipse::setShowPercent(bool showPercent)
{
    _P->m_showPercent = showPercent;
    update();
    return *this;
}

void LPProcessEllipse::startTimer()
{
    _P->m_startTimer->start(100);
}
